字符串
    由一系列的字符组成，每个字符占一个字节，只支持256字符集
    PHP的字符串支持最大长度为2G
    PHP表示字符串形式:
        单引号      不解析字符串中的特殊符号，速度更快
        双引号      会解析字符串中的特殊符号
            \n      换行，ASCII字符集中 LF或0x0A(10)
            \r      回车，ASCII字符集中 CR或0x0D(13)
            \t      水平制表符，ASCII字符集中 HT或0x09(9)
            \v      垂直制表符，ASCII字符集中 VT或0x11(17)
            \e      ESCAPE ASCII字符集中 ESC或0x1B(27)
            \f      换页 ASCII字符集中 FF或0x0C(12)
            \\      反斜杠
            \$      打印$美元符号
            $       解析变量值
            \"      打印双引号

        HereDoc语法 <<< 表示大批量的字符串(解析特殊字符)
            格式：$变量名 = <<< 结束标识符  //结束标识符后没有分号
                    ....
                  结束标识符; //结束标识符独立一行,
                              //结束标识符前面不能有任何字符，包括空格
                              //结束标识符后面只有一个分号

        NewDoc语法 <<< 表示大批量的字符串(不解析特殊字符)
            格式: $变量名 = <<< '结束标识符'
                    ...
                  结束标识符;

    字符串连接运算符    .
        格式：
            $变量名 = 字符串1.字符串2;
            $变量名 .= 字符串2;

    字符串的字符操作(PHP5.5才支持)
        字符串的字符可以通过中括号或大括号来访问
            $变量名[下标] / $变量名{下标};

    字符串类型转换(string/strval)
        整型与浮点型转字符串，值不变
        布尔型转字符串，true为"1", false为空字符串""
        数组转字符串, 值Array
        NULL转字符串为空

字符串操作函数
    w3m http://3.3.3.1/php_manual/book.strings.html

    ASCII相关操作函数
        ord         将字符转成ASCII值
        chr         返回对应ASCII值的字符

    前后字符删除操作(去空格)
        trim
        rtrim/chop
        ltrim

    字符串分割
        chunk_split
        strtok
        str_split
        explode

    大小写转换
        strtolower
        strtoupper
        strtr
        lcfirst
        ucfirst
        ucwords

    字符串输出
        echo
        print
        printf
        sprintf
        fprintf
        vfprintf
        vprintf
        vsprintf

    与html相关
        htmlentities
        html_entity_decode
        htmlspecialchars
        htmlspecialchars_decode
        nl2br
        strip_tags

    字符串编码
        crypt
        md5_file
        md5
        sha1_file
        sha1
        str_rot13

    字符串替换
        str_replace
        str_ireplace
        substr_replace
        wordwrap

    字符串比较
        strcmp
        strncmp
        strcasecmp
        strnatcmp
        strnatcasecmp
        substr_compare

    字符串查找
        strstr/strchr
        strrchr
        stristr
        strpos
        stripos
        strrpos
        strirpos
        strpbrk
        strcspn
        strspn

    字符串截取
        substr

    字符串长度
        strlen      获取某个字符串的长度

    字符串反转
        strrev

    字符串打乱
        str_shuffle

    字符串填充
        str_pad

    数组连接为字符串
        implode/join

    字符串重复
        str_repeat

    格式化输入字符
        sscanf

    字符串统计
        str_word_count
        substr_count

    字符串与变量
        parse_str
--------------------------------------------------------
字符编码 UTF-8
    unicode  <--> UTF-8

    iconv       对字符串的字符编码转化的函数

    mb_开头的函数可以处理多字节的字符串
    mb_strlen       获取字符串长度

--------------------------------------------------------
正则表达式   -  查找
    描述字符串结构的语法规则，是一个特定的格式化模式，用于匹配、替换、截取匹配等子串
    最初由UNIX的工具软件普及(grep)
        ED编辑器的一条命令, 显示文件中特定的内容
        独立工具 -- grep, egrep增强正则表达式的功能
        POSIX标准规范正则表达式
        perl脚本语言在POSIX标准之上实现另一个标准(PCRE)

    PHP支持两种正则表达式的标准，5.3以后不建议使用POSIX标准的正则表达式

    PHP支持PCRE正则表达式的函数
        preg_grep           返回匹配模式的数组条目
        preg_match          执行一个正则表达式的匹配
        preg_match_all      执行一个全局正则表达式的匹配
        preg_quote          转义正则表达式字符
        preg_split          正则表达式分割字符串
        preg_replace        执行一个正则表达式的搜索和替换

    正则表达式由两部分组成: 文本字符与元字符
        元字符是具有特殊意义的字符
        文本字符就是普通字符
        pcre风格会将正则表达式放置在定界符之间: /正则表达式/

元字符
    行定位符 锚
        ^    表示行开始
        $    表示行结尾
            例：
                ^abc        以abc开头的行
                ^abc$       行里内容只有abc

    字符类 []
        []   代表匹配括号中的一个字符
            连字符      -   在中括号表示范围
            排除字符    ^   中括号只能写一个排除字符，必须是中括号里开头位置, 代表只要不是中括号里的字符都满足匹配
            例：
                [abc]       代表此字符是a或b或c
                [^abc]      代表此字符只要不是abc都满足
                [0-9]       代表此字符是数字0到9其中任意一个
                [a-zA-Z]    代表此字符是26个英文字母(大小写)
        预定义字符类
            [[:alnum:]]     字母数字

    选择字符 |
        |       代表或的意思, 与[]不同可以匹配任意长度
        例：
            a|b         表示此字符是a或者是b
            cat|dog     表示此字符串为cat或dog

    点字符
        .       代表任意一个字符

    限定符(量词 重复序列) ? + * {n,m}
        ?       匹配前面一个字符重复0次或1次{0,1}
        +       匹配前面一个字符重复1次或多次{1,}
        *       匹配前面一个字符重复0次或多次{0,}
        {n}     匹配前面一个字符重复n次
        {n,}    匹配前面一个字符重复至少n次
        {n,m}   匹配前面一个字符重复n到m次

        默认贪婪匹配模式, 最大匹配，匹配最后一个
            <p class="name">hello</p>
            /<(.*)>/      匹配最后一个>
                子模式匹配结果: p class="name">hello</p
            解决方法: /<([^>]+).*/
                匹配结果： p class="name"


    转义字符
        \       将后面字符失去特殊意义

        \n \t \r ...
        \d      等于同[0-9]+
        \w      等于同[a-zA-Z0-9 _]
        \W      等于同[^a-zA-Z0-9 _]
        \s      任意空白字符
        \S      非任意空白字符

    断言/锚
        ^       以什么开头
        $       以什么结尾
        \b      定位完整单词边界
            \babc   以abc开头的单词
            abc\b   以abc结尾的单词
            \babc\b 完整匹配abc单词
        \B      定位子串必须在某个单词中, 默认效果

    小括号字符 ()
        第一个作用改变元字符的作用范围:
            runing|kyoing 可以写成: (run|kyo)ing

        第二个作用是分组，即子表达式(子模式)
            子表达式具有记忆功能，可以通过反引用来获取记忆匹配结果
            例：
                ([a-z]+)[^a-zA-Z0-9]+([0-9]+)
                \1      [a-z]+匹配的结果
                \2      [0-9]+匹配的结果
                ...
                以此类推

            对分组命名
                (?P=<ch>[a-z]+)[^a-zA-Z0-9]+(?P=<num>[0-9]+)
                (?P=ch)      [a-z]+匹配的结果
                (?P=num)     [0-9]+匹配的结果
                ...
                以此类推

            不需要匹配子模式的指定文本，可以使用非捕获组
                (?:hello)(.*)       不会匹配hello

    模式修饰符(子表达式选项)
        i       忽略大小写匹配
        m       多行匹配模式, 使^可以匹配\n之后的内容, 使$可以匹配\n之前的内容
        s       单行匹配模式， 使点匹配任意字符，包括\n， 默认使用单行
        x       忽略空白和注释

        PHP扩展模式修饰符
            U       颠倒子模式贪婪性，设置量词为非贪婪性
            u       将字符串作为UTF-8编码处理, 默认操作
            D       使$字符仅匹配一行末尾, 设置m模式忽略此选项
            S       使第二次使用子模式加速度

        使用方法：
            后缀全局式：/[a-z]+/i
            内联局部式: /(?i:[a-z]+)[^a-zA-Z]/
            混合式:/(?-i:[a-z]+)[^a-z]/i
                    全局忽略大小写匹配， 但子表达式不忽略大小写匹配

    前向或后向断言
        (?=子表达式)     正前向  下一个文本必须是子表达式的匹配
        (?<=子表达式)    正后向  上一个文本必须是子表达式的匹配
        (?!子表达式)     负前向  下一个文本必须不是子表达式的匹配
        (?<!子表达式)    负后向  上一个文本必须不是子表达式的匹配

        拆分字符串中非常有用
            preg_split('/(?=kyo)/m', $str);
                以kyo为分隔符分割字符串
                    正前向将kyo放在后面表达中
                    正后向将kyo放在前面表达中

    条件表达式
        (?(条件)条件成立表达式)
        (?(条件)条件成立表达式|条件不成立表达式)

    注释
        在子表达式中可以使用#注释


不要事必正则表达式，能用PHP字符串函数实现就不要使用正则表达式(效率/性能问题)
str_replace比preg_replace函数效率高， strtr效率是str_replace的四倍

---------------------------------------------------------
sed命令 流编辑器
    删除(过滤输出) d
        删除第一行
            sed "1d" /etc/passwd

        删除第一行到第三行和第五行
            sed "1,3d;5d" /etc/passwd

        删除匹配root开头的行
            sed "/^root/d"  /etc/passwd

        删除以小写字母开头的行
            sed -r "/^[a-z]/d" /etc/passwd

        删除空行
            sed -r "/^$/d" /etc/passwd

        删除数字结尾的行
            sed -r "/[0-9]$/d" /etc/passwd

        删除以空格开头的行
            sed -r "/^ /d"  /etc/passwd
            sed -r "/^[[:blank:]]/d" /etc/passwd

        删除以特殊符号开头的行
            sed -r "/^[^a-zA-Z0-9]/d" /etc/passwd
            sed -r "/^[[:punct:] ]/d" /etc/passwd

    打印    p
        打印第一行
            sed -n "1p" /etc/passwd

        打印第一行和第三行
            sed -n "1p;3p" /etc/passwd

        打印第一行到第三行
            sed -n "1,3p" /etc/passwd

        打印匹配root开头的行
            sed -nr "/^root/p" /etc/passwd

        打印以小写字母开头和以nologin结尾的行
            sed -nr "/^[a-z]/p;/nologin$/p" /etc/passwd

        打印以root开头和以ftp开头的行
            sed -nr "/^root/p;/^ftp/p" /etc/passwd

        打印以root开头到以ftp开头的行
            sed -nr "/^root/,/^ftp/p" /etc/passwd

    替换    s
        将文件中的第一个root替换成kyo
            sed -r "s/root/kyo/"  /etc/passwd

        将文件中的第三个root替换成kyo
            sed -r "s/root/kyo/3"  /etc/passwd

        将文件中的全部root替换成kyo
            sed -r "s/root/kyo/g"  /etc/passwd

        将文件中的10到20行全部root替换成kyo
            sed -r "10,20s/root/kyo/g" /etc/passwd

        将root替换成rootboot, &代表前面被替换的字符
            sed -r "s/root/&boot/" /etc/passwd

        把以bin开头的行到以adm开头的行中，把全部root替换成rootkyo
            sed -nr "/^bin/,/^adm/s/root/&kyo/gp" /etc/passwd

        删除每行的第一个字符
            sed -nr "s/^.(.*)/\1/p" /etc/passwd

        删除每行的第二个字符
            sed -nr "s/^(.{1}).(.*)/\1\2/p" /etc/passwd

        删除每行的第三个字符
            sed -nr "s/^(.{2}).(.*)/\1\2/p" /etc/passwd

        打印每行的第一个单词
            sed -nr "s/^[^a-zA-Z]*\b([a-zA-Z]+)\b.*/p" /etc/passwd

        打印每行的每一个单词和第三个单词
            sed -nr "s/^[^a-zA-Z]*([a-zA-Z]+)[^a-zA-Z]+[a-zA-Z]+[^a-zA-Z]+([a-zA-Z]+).*/\1 \2/p" /etc/passwd

        删除每一行的最后一个单词
            sed -nr "s/(.*[^a-zA-Z]+)[a-zA-Z]+$/\1/p" /etc/passwd

        删除每一行的倒数第二个单词(前提一行大于2个单词)
            sed -nr "s/(.*[^a-zA-Z]+)[a-zA-Z]+([^a-zA-Z]+[a-zA-Z]+)$/\1\2/p" /etc/passwd
            如果一行只有两个单词匹配不到

        每行第二个单词与第三个单词进行交换
            sed -nr "s/(^[^a-zA-Z]*[a-zA-Z]+[^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+.*$)/\1\4\3\2\5/p"  /etc/passwd

        每行第二个单词与倒数第二个单词进行交换(前提一行大于2个单词)
            sed -nr "s/(^[^a-zA-Z]*[a-zA-Z]+[^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+.*[^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+[a-zA-Z]+[^a-zA-Z]*$)/\1\4\3\2\5/p"  /etc/passwd
            如果一行只有两个单词匹配不到

        使用sed一行命令截取IP地址/子网掩码
            3.3.3.9/255.255.255.0

        LANGUAGE=en_US:en; ifconfig enp0s25 | sed -nr "s/inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*Mask:(.*)/\1\/\2/p"

------------------------------------------------------------------------
Awk
    Awk是一门编程语言，有很多版本，我们用的是GNU的gawk

        以:为分隔符打印第三列

            awk -F : '{print $3}' /etc/passwd

        以:为分隔符统计/sbin/nologin有多少个

            awk 'BEGIN{FS=":" ;count=0}{if($7 = "/sbin/nologin")count+=1}END{print count}' /etc/passwd

                BEGIN      在读记录之前执行
                END        在读完记录后再执行
                $0         代表所有记录
                $1-n       代表一个记录的第几个字段

        使用awk脚本

            #!/bin/awk

            BEGIN{
                FS=:
                count=0         定义变量
            }

            {
                if($7 == "/sbin/nologin")
                {
                    count += 1
                    print $0
                }
            }

            END{
                print "count="count
            }

            awk -f 1.awk /etc/passwd        运行上面的脚本

            FNR         当前处理到第几个文件
            NF          当前多个个字段
            NR          当前处理到第几个记录
            OFS         输入指定字段分隔符
            ORS         输出记录分隔符


        打印所有行
            awk '{ print $0 }' /etc/passwd

        打印第一列
            awk -F ":" '{print $1}' /etc/passwd

        打印第一列和第三列
            awk -F ":" '{print $1"\t"$3" welcome"}' /etc/passwd

        打印每行的最后一列
            awk -F : '{print $NF}' /etc/passwd

        打印第八行
            awk -F : '{if (NR == 8){print $0}}' /etc/passwd
            awk -F : 'NR == 8 {print $0}' /etc/passwd

        打印行总数
            awk -F : 'END{print NR}' /etc/passwd

        打印每行的字段数
            awk -F : '{print NF}' /etc/passwd

        打印最后一行的最后一列
            awk -F : 'END{print $NF}' /etc/passwd

        打印字段数大于4的行
            awk -F : 'NF > 4 {printf $0}' /etc/passwd

        打印文件里所有字段总数
            awk -F : 'BEGIN{c = 0}{c=c+NF}END{print c}' /etc/passwd

        打印uid在30~40范围内的用户名
            awk -F : '$3 >= 30 && $3 <= 40{print $1}' /etc/passwd

        打印5到56行
            awk -F : 'NR >= 5 && NR <= 56 {print $0}' /etc/passwd

        隔行删除
            awk '{if (NR % 2 == 0)print $0}' /etc/passwd

        打印每行的第一单词
            awk 'BEGIN{FS="[^A-Za-z]"}{print $1}' /etc/passwd

        打印每行的第一个和第三个单词
            awk 'BEGIN{FS="[^a-zA-Z]+"}{print $1,$3}' /etc/passwd

        打印字段数大于5个的行总数
            awk 'BEGIN{FS=":";sum=0}{NF > 5{sum=sum+1}}END{print sum}' /etc/passwd

=====================================================================
作业：
    字符串数字相加/计算五十位数字相加
        $a = "123";
        $b = "789";

    统计字符串单词个数(单词分隔符为除26个英文字母外)
    (str_word_count)
        考虑重复分隔符问题

    0 == false    结果为真
    0 === false   结果为假

    用户输入两个字符串， 连接两字符串并且去除两字符串重复单词输出
        单词分隔符为空格，处理连接分隔符问题
        例：
            输入：
                what is your name
                my name is kyo

            输出: what your my kyo

    用户输入字符串，对此字符串按单词进行反转输出
        例:
            输入：how are you
            输出：you are how

    输出两个字符串的最大公共子串
        例：
            howareyou
            hwwarett
        输出： ware

    输入字符串，对其字符串提取数字累加输出之和
        输入：sdf123sdfkj456sfjd12
        输出： 123 + 456 + 12 = 591


vim:ft=php:
